#pragma once
#include <string>
#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <jsoncpp/json/json.h>
namespace na_protocol
{
//#define MYSELF 0
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define SEP "\r\n"
#define SEP_LEN strlen(SEP)

    class Request
    {
    public:
        Request()
        {
        }
        Request(int x, char op, int y)
            : _x(x), _y(y), _op(op)
        {
        }
        std::string Serialize()
        { // 序列化  1024 + 5678
#ifdef MYSELF
            std::string str;
            str += std::to_string(_x);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_y);
            return str;
#else
         Json::Value root;
         root["x"]=_x;
         root["y"]=_y;
         root["op"]=_op;
         Json::FastWriter writer;
         return writer.write(root);





#endif
        }

        bool Deserialized(std::string &str) // 反序列化
        {
#ifdef MYSELF

            ssize_t left = str.find(SPACE);
            if (left == std::string::npos)
                return false;
            ssize_t right = str.rfind(SPACE);
            if (right == std::string::npos)
                return false;
            _x = atoi(str.substr(0, left).c_str());
            _y = atoi(str.substr(right + SPACE_LEN).c_str());
            _op = str[left + SPACE_LEN];
            return true;
#else

          Json::Value root;
          Json::Reader reader;
          reader.parse(str,root);
          _x=root["x"].asInt();
          _y=root["y"].asInt();
          _op=root["op"].asInt();
          return true;
#endif
        }
        ~Request()
        {
        }

        int _x;
        int _y;
        char _op;
    };

    class Response
    {
    public:
        Response()
        {
        }
        Response(int code, int result)
            : _code(code), _result(result)

        {
        }
       
        std::string Serialize() // 序列化
        {
#ifdef MYSELF
            std::string s;
            s += std::to_string(_code);
            s += SPACE;
            s += std::to_string(_result);
            return s;
#else
       Json::Value root;
       root["result"]=_result;
       root["code"]=_code;
      Json::FastWriter writer;
      return writer.write(root);
#endif
        }
        bool Deserialized(std::string &str) // 反序列化
        {
#ifdef MYSELF
            ssize_t pos = str.find(SPACE);
            if (pos == std::string::npos)
                return false;
            _code = atoi(str.substr(0, pos).c_str());
            _result = atoi(str.substr(pos + SPACE_LEN).c_str());
            return true;
#else 
          Json::Value root;
          Json::Reader reader;
          reader.parse(str,root);
          _result=root["result"].asInt();
          _code=root["code"].asInt();
          return true;



#endif
        }
        ~Response()
        {
        }

        int _code;   // 结果码
        int _result; // 计算结果
        int _x;
        int _y;
        char _op;
    };

    bool Recv(int sock, std::string *out)
    {
        char buff[1024];
        ssize_t s = recv(sock, buff, sizeof(buff) - 1, 0);
        if (s > 0)
        {
            buff[s] = 0;
            *out += buff;
        }
        if (s == 0)
        {
            std::cout << "client quit I quit" << std::endl;
            return false;
        }
        if (s < 0)
        {
            std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }
    void Send(int sock, std::string &str)
    {
        ssize_t s = send(sock, str.c_str(), str.size(), 0);
        if (s < 0)
        {
            std::cout << "send error" << std::endl;
        }
    }
    std::string Decode(std::string &str) // 对于传来的报文提取有效信息   9\r\n123 + 234\r\n
    {
        int pos = str.find(SEP);
        if (pos == std::string::npos)
        {
            return "";
        }
        int size = atoi(str.substr(0, pos).c_str());  // 报文中第一个字符表示一条正常有效信息的长度，即报头
        int surplus = str.size() - pos - 2 * SEP_LEN; // 实际传过来的有效信息长度
        if (surplus >= size)                          // 至少可以提取一条有效信息
        {
            str.erase(0, pos + SEP_LEN);         // 删除报头以及分隔符SEP
            std::string s = str.substr(0, size); // 提取一条有效信息
            str.erase(0, size + SEP_LEN);        // 删除已经提取到的有效信息以及后面的分隔符SEP，保证下次提取信息从一条新的完整报文中提取
            return s;
        }
        else
        {
            return "";
        }
    }
    std::string Encode(std::string &str) // 为有效信息添加报头以及分隔符
    {
        std::string new_package = std::to_string(str.size());
        new_package += SEP;
        new_package += str;
        new_package += SEP;
        return new_package;
    }
}
